<?php
class Reale_Model_Users_AgentMapper
{
    /**
     * @var Zend_Db_Table_Abstract
     */
    protected $_dbTable;
    /**
     * Specify Zend_Db_Table instance to use for data operations
     * 
     * @param  Zend_Db_Table_Abstract $dbTable 
     * @return Reale_Model_Users_AgentMapper
     */
    public function setDbTable ($dbTable)
    {
        if (is_string($dbTable)) {
            $dbTable = new $dbTable();
        }
        if (! $dbTable instanceof Zend_Db_Table_Abstract) {
            throw new Exception('Invalid table data gateway provided');
        }
        $this->_dbTable = $dbTable;
        return $this;
    }
    /**
     * Get registered Zend_Db_Table instance
     *
     * Lazy loads Reale_Model_DbTable_Agent if no instance registered
     * 
     * @return Reale_Model_DbTable_Agent
     */
    public function getDbTable ()
    {
        if (null === $this->_dbTable) {
            $this->setDbTable('Reale_Model_DbTable_Agent');
        }
        return $this->_dbTable;
    }
    /**
     * 
     * Checks username for availability.
     * 
     * @return Boolean
     * true => if username available
     * false => if username alreaddy used.
     */
    public function checkUsername ($username)
    {
        $where = array('username' => $username);
        $check = $this->getDbTable()->fetchRow($where);
        if (count($check) != 0) {
            return false; //username already taken.
        } else {
            return true; //username available.
        }
    }
    /**
     * 
     * To save new or update existing agent's informtion.
     * @param Reale_Model_Users_Agent
     * @return Reale_Model_Users_Agent | null 
     */
    public function save (Reale_Model_Users_Agent &$agent)
    {
        $agentdata = array('agent_reg_id' => $agent->getAgent_reg_id(), 
        'agent_name' => $agent->getAgent_name(), 
        'father_name' => $agent->getFather_name(), 
        'mother_name' => $agent->getMother_name(), 
        'mobile_no' => $agent->getMobile_no(), 
        'alternate_no' => $agent->getAlternate_no(), 
        'occupation' => $agent->getOccupation(), 
        'rgrn_date' => $agent->getRgrn_date(), 'dob' => $agent->getDob(), 
        'applicant_type_id' => $agent->getApplicant_type_id(), 
        'gender_id' => $agent->getGender_id(), 
        'nationality_id' => $agent->getNationality_id(), 
        'marital_status_id' => $agent->getMarital_status_id(), 
        'pan' => $agent->getPan(), 'email' => $agent->getEmail(), 
        'password' => $agent->getPassword());
        if ($agent->getHusband_name()) {
            $agentdata['husband_name'] = $agent->getHusband_name();
        }
        if ($agent->getAgent_type_spec()) {
            $agentdata['agent_type_spec'] = $agent->getAgent_type_spec();
        }
        $authUser = new Reale_Model_DbTable_AuthUser();
        $authUserdata = array('user_id' => $agent->getAgent_reg_id(), 
        'sec_passwd' => $agent->getPassword(), 'user_type_id' => 'agnt');
        try {
            $this->getDbTable()
                ->getAdapter()
                ->beginTransaction();
            /*
             * Insert Agent Basic data
             */
            $pKey = $this->getDbTable()->insert($agentdata);
            /*
             * Agent Sponsorship
             */
            $sponsorer = $agent->getSponsor();
            $sponsorer->sponsor($agent);
            /*
             * Agent Authentication
             */
            $authUser->insert($authUserdata);
            $userRole = new Reale_Model_DbTable_UserRole();
            $userRole->insert(
            array('user_id' => $agent->getAgent_reg_id(), 'role_id' => 'agent'));
            /*
             * Agent Addresses
             */
            $padd = $agent->getPaddress();
            $cadd = $agent->getCaddress() ? $agent->getCaddress() : '';
            $add_data = array('agent_id' => $agent->getAgent_id(), 
            'paddress' => $padd->getAddressline(), 'pplace' => $padd->getPlace(), 
            'pdistrict' => $padd->getDistrict(), 'pstate' => $padd->getState(), 
            'ppostalcode' => $padd->getPostalcode());
            if ($cadd) {
                $add_data['caddress'] = $cadd->getAddressline();
                $add_data['cplace'] = $cadd->getPlace();
                $add_data['cdistrict'] = $cadd->getDistrict();
                $add_data['cstate'] = $cadd->getState();
                $add_data['cpostalcode'] = $cadd->getPostalcode();
            }
            $cadd = $agent->getCaddress() ? $agent->getCaddress() : '';
            $agentAddress = new Reale_Model_DbTable_AgentAddress();
            $agentAddress->insert($add_data);
            /*
             * Nominee Address
             */
            $nominee = $agent->getNominee();
            $nom_data = array('agent_id' => $agent->getAgent_id(), 
            'nominee_name' => $nominee->getNominee_name(), 
            'relation' => $nominee->getRelation(), 'pan' => $nominee->getPan(), 
            'address' => $nominee->getAddress()->getAddressline(), 
            'place' => $nominee->getAddress()->getPlace(), 
            'district' => $nominee->getAddress()->getDistrict(), 
            'state' => $nominee->getAddress()->getState(), 
            'postalcode' => $nominee->getAddress()->getPostalCode());
            $agentNominee = new Reale_Model_DbTable_AgentNominee();
            $agentNominee->insert($nom_data);
            /*
             * Agent Register transaction.
             */
            $agentRegister = new Reale_Model_DbTable_AgentRegister();
            $agentRegister->insert(array('agent_id' => $agent->getAgent_id()));
            $this->getDbTable()
                ->getAdapter()
                ->commit();
        } catch (Exception $e) {
            $this->getDbTable()
                ->getAdapter()
                ->rollBack();
            throw $e;
        }
        return $agent;
    }
    public function delete (Reale_Model_Users_Agent &$agent)
    {
        try {
            $this->getDbTable()
                ->getAdapter()
                ->beginTransaction();
            $affectedRows = $this->getDbTable()->delete($agent->getAgent_reg_id());
            $this->getDbTable()
                ->getAdapter()
                ->commit();
            return $affectedRows;
        } catch (Exception $e) {
            $this->getDbTable()
                ->getAdapter()
                ->rollBack();
            throw $e;
        }
    }
    public function fetchPendingDisbursements ()
    {
        $dbTable = new Reale_Model_DbTable_AgentRegister();
        return $dbTable->fetchPendingDisbursements();
        
    }
    /**
     * Upgrade the business level of a particular agent.
     * @param Reale_Model_Users_Agent $agent
     */
    protected function _upgradeBusinessLevel (Reale_Model_Users_Agent $agent)
    {
        $newlevel = self::_upgradableLevel($agent);
        if ($newlevel) {
            $currentLevel = $agent->currentBusinessLevel();
            if ($currentLevel < $newlevel) {
                $achievement = new Reale_Model_DbTable_AgentAchievement();
                $data = array('business_level_no' => $newlevel, 
                'agent_id' => $agent->getAgent_id());
                return $achievement->insert($data);
            }
        }
    }
    /**
     * If business level to be upgraded, then it will suggest the new level, else return null.
     * @param Reale_Model_Users_Agent $agent
     */
    protected function _upgradableLevel (Reale_Model_Users_Agent $agent)
    {
        $agentJustBelow = $agent->fetchDownLine(null, 1);
        $currentLevel = $agent->currentBusinessLevel();
        $agents = array_keys($agentJustBelow);
        $childLevel = array();
        foreach ($agents as $agent_id) {
            $agent = new Reale_Model_Users_Agent(array('agent_id' => $agent_id));
            $childLevel[] = $agent->currentBusinessLevel();
        }
        $max = Reale_Model_Users_Agent::MAX_SPONSOR;
        $rootID = Reale_Model_Users_Agent::ROOT_AGENT_ID;
        if (($max == count($childLevel)) and ($agent->getAgent_id() != $rootID)) {
            $uniqueLevel = array_unique($childLevel);
            if (1 == count($uniqueLevel)) {
                $upgradeTo = $uniqueLevel[0] + 1;
                return $upgradeTo;
            }
        }
        return null;
    }
    /**
     * Update the business level of a agent and parents.
     * @param Reale_Model_Users_Agent $agent
     */
    public function updateBusinessTree (Reale_Model_Users_Agent $agent)
    {
        $logger = Zend_Registry::get('logger');
        $upLine = $agent->fetchUpline();
        $logger->info('Upline agents:');
        $logger->debug($upLine);
        for ($agentNo = 0; $agentNo < count($upLine); $agentNo ++) {
            $agent = new Reale_Model_Users_Agent(array('agent_id' => $upLine[$agentNo]));
            $upgrade = self::_upgradeBusinessLevel($agent);
            if (is_null($upgrade)) {
                $lastSucess = $agentNo-1;
                $logger->info('Upgraded agent(s) below:');
                $logger->debug($agent->getAgent_reg_id());
                return 'Upgraded upto : '.$upLine[$lastSucess];
            } else {
                $logger->info('Upgraded agent : ' . $agent->getAgent_reg_id());
                $logger->debug($upgrade);
            }
        }
    }
    
    
	public function fetchNetworkAccount ($agent_id = NULL,$dispatched = NULL, $dispatchDate = NULL, $transDate = NULL)
    {
        $dbTable = new Reale_Model_DbTable_AgentEarnings();
        return $dbTable->networkTransactions($agent_id,$dispatched, $dispatchDate, $transDate);
    }
    
	public function fetchBusinessAccount ($agent_id = NULL,$dispatched = NULL, $dispatchDate = NULL, $transDate = NULL)
    {
        $dbTable = new Reale_Model_DbTable_AgentEarnings();
        return $dbTable->businessTransactions($agent_id,$dispatched, $dispatchDate, $transDate);
    }
    
}

